"""
Author: Jian SuiYue kaohx0214@yeah.net
Date: 2025-04-28 02:39:52
LastEditTime: 2025-05-19 23:51:53
FilePath: LibraryManagerStudio/web/routes/category_api.py
"""
from fastapi import APIRouter, Depends, HTTPException, status, Query
from fastapi.responses import JSONResponse

from .token_api import validate_jwt
from ..deps import get_db
from ...database import DBManager
from ...datamodel import Category, CategoryBase, CategoryUpdate, Book

router = APIRouter()


@router.get("/get")
async def get(
        login: str = Query(...),
        category_id: int = Query(..., ge=1),
        db: DBManager = Depends(get_db)
):
    """
    get category by its id

    Get /get?login={your_token}&category_id={category_id}
    Args:
        login: Token.id
        category_id: Category.id
        db: DBManager
    """
    validate_jwt(login, db)
    category = db.get(Category, filters={"id": category_id})
    if not category.status or not category.data:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Category ID: {category_id} Not found")
    
    return {"status": True, "data": category.data[0]}


@router.post("/gets")
async def gets(
        login: str = Query(...),
        page: int = Query(..., ge=1),
        size: int = Query(..., ge=10, le=100),
        db: DBManager = Depends(get_db)
):
    """
    Get categories by page and size

    POST /gets?login={your_token}&page={page}&size={size}
    Args:
        login: Token.id
        page: page
        size: size
        db: DBManager
    """
    validate_jwt(login)
    categories = db.get(Category, page_info={"page": page, "size": size})
    if not categories.status or not categories.data:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=f"Unexpected Error: {categories.message}")
    return JSONResponse(
        status_code=status.HTTP_200_OK,
        content={"status": True, "data": categories.data, "message": "get categories successful"}
    )


@router.post("/new")
async def new_category(
        category_info: CategoryBase,
        login: str = Query(...),
        db: DBManager = Depends(get_db)
):
    """
    New a category

    POST /new?login={your_token}
    Args:
        category_info: CategoryBase
        login: Token.id
        db: DBManager
    """
    validate_jwt(login)
    category_exist = db.get(Category, filters={"id": category_info.id})
    if category_exist.status and category_exist.data:
        raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=f"The Category: {category_info.name} is exist")
    name_exist = db.get(Category, filters={"name": category_info.name})
    if name_exist.status and name_exist.data:
        raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=f"The Category: {category_info.name} is exist")
    category = Category(name=category_info.name, description=category_info.description)
    result = db.upsert(category)
    return JSONResponse(
        status_code=status.HTTP_200_OK,
        content={"status": True, "data": result.data[0], "message": "New table successful"}
    )


@router.put("/update")
async def update_category(
        category: CategoryUpdate,
        login: str = Query(...),
        db: DBManager = Depends(get_db)
):
    """
    Only offer update the category description !!!!

    PUT /update?login={your_token}
    Args:
        login: Token.id
        category: Category
        db: DBManager
    """
    validate_jwt(login)
    category_exist = db.get(Category, filters={"id": category.id})
    if not category_exist.status and not category_exist.data:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"The Category: {category.name} not found")

    if category.name:
        name_exist = db.get(Category, filters={"name": category.name})
        if name_exist.status and name_exist.data:
            raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=f"The Category: {category.name} is exist")

    origin = category_exist.data[0]
    for field, value in category.model_dump():
        if value is not None:
            setattr(origin, field, value)

    response = db.upsert(Category(**origin))
    if not response.status:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=f"UnExpected Error: {response.message}")

    return JSONResponse(
        status_code=status.HTTP_200_OK,
        content={"status": True, "data": response.data[0], "message": "Update table successful"}
    )


@router.delete("/delete")
async def delete_category(
        login: str = Query(...),
        category_id: int = Query(..., ge=1),
        db: DBManager = Depends(get_db)
):
    """
    Delete category table data by its id

    DELETE /delete?login={your_token}&category_id={category_id}
    Args:
        login: Token.id
        category_id: The category id
        db: DBManager
    """
    validate_jwt(login)
    category = db.get(Category, filters={"id": category_id})
    if not category.status and not category.data:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"The Category ID: {category_id} not found")

    # Book have the category_id(foreign_key), set the category_id to None
    origin = db.get(Book, filters={"category_id": category_id}).data
    for book in origin:
        book["category_id"] = None
        db.upsert(Book(**book))

    db.delete(Category, filters={"id": category_id})

    return JSONResponse(
        status_code=status.HTTP_200_OK,
        content={"status": True, "message": "Delete table successful"}
    )
